package com.leyou.search.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.bo.SpuBo;
import com.leyou.item.pojo.Sku;
import com.leyou.item.pojo.SpecParam;
import com.leyou.item.pojo.Spu;
import com.leyou.item.pojo.SpuDetail;
import com.leyou.search.clients.CategoryClient;
import com.leyou.search.clients.GoodsClient;
import com.leyou.search.clients.SpecClient;
import com.leyou.search.pojo.Goods;
import com.leyou.search.repository.GoodsRepository;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class IndexService {
    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private SpecClient specClient;
    @Autowired
    private GoodsRepository goodsRepository;

    //数据倒入的过程其实就是把spu变成 ---》goods对象的过程，并且把goods对象通过repository接口对象保存到索引库中
    public Goods buildGoods(SpuBo spu) {
        Goods goods = new Goods();
        BeanUtils.copyProperties(spu, goods);
        Long spuId = spu.getId();
        //准备数据
        //查询商品分类名称
        List<String> names = this.categoryClient.queryNameByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
        String all = spu.getTitle() + " " + StringUtils.join(names, " ");
        goods.setAll(all);
        //根据spuId查询sku
        List<Sku> skus = this.goodsClient.querySkuBySpuId(spuId);
        //处理sku
        //把商品价格取出单独存放，便于展示
        //创建存放price 和sku json集合
        List<Long> price = new ArrayList<>();
        List<Map<String, Object>> skuList = new ArrayList<>();
        for (Sku sku : skus) {
            price.add(sku.getPrice());
            Map<String, Object> skuMap = new HashMap<>();
            skuMap.put("id", sku.getId());
            skuMap.put("title", sku.getTitle());
            skuMap.put("image", sku.getImages());
            skuMap.put("price", sku.getPrice());
            skuList.add(skuMap);
        }
        goods.setPrice(price);
        goods.setSkus(JsonUtils.serialize(skuList)); //讲skuList 转成 json 字符串

        // 可搜索的规格参数，key是参数名(spec-param)，值是参数值(spuDetail || genericSpec,specailSpec)
        //存放进goods中的最终规则参数键值对
        Map<String, Object> specs = new HashMap<>();//操作系统：Android，Cpu品牌：骁龙

        //获取到所有的可搜索的规格参数(tb_spec_param表中searching=1的)
        List<SpecParam> specParams = this.specClient.querySpecParam(null, spu.getCid3(), true, null);

        //查询spuDetail，然后获取其中的通用规格参数以及特有规格参数
        SpuDetail spuDetail = this.goodsClient.querySpuDetailById(spuId);

        //从spuDetail中获取所有的通用规格参数的具体的值(spu_detail表中的Generic_spec字段)把jsonString转成map
        Map<Long, Object> genericSpecMap = JsonUtils.parseMap(spuDetail.getGenericSpec(), Long.class, Object.class);

        //从spuDetail中获取特有的规格参数的具体的值(special_spec字段)
        Map<Long, List<String>> specialSpecMap = JsonUtils.nativeRead(spuDetail.getSpecialSpec(),
                new TypeReference<Map<Long, List<String>>>() {
                });

        //迭代可搜索规格参数，动态处理成最终key：value结构
        specParams.forEach(specParam -> {
            Long paramId = specParam.getId();
            String name = specParam.getName();

            //通用参数
            Object value = null;
            if (specParam.getGeneric()) {
                //通用参数
                value = genericSpecMap.get(paramId);

                if (specParam.getNumeric()) {
                    //数值类型需要加分段
                    value = this.chooseSegment(value.toString(), specParam);
                }
            } else {//特有参数
                value = specialSpecMap.get(paramId);

            }
            if (null == value) {
                value = "其他";
            }
            specs.put(name, value);
        });
        goods.setSpecs(specs);
        return goods;
    }

    private String chooseSegment(String value, SpecParam p) {
        double val = NumberUtils.toDouble(value);
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = NumberUtils.toDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = NumberUtils.toDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    public void createIndex(Long id) {
        Spu spu = this.goodsClient.querySpuById(id);
        SpuBo spuBo = new SpuBo();
        BeanUtils.copyProperties(spu, spuBo);
        Goods goods = this.buildGoods(spuBo);
        this.goodsRepository.save(goods);
    }

    public void deleteIndex(Long id) {
        this.goodsRepository.deleteById(id);
    }
}
